<?php
require $root . '/Map/BinarySearchTreeMap.php';
require 'HashCode.php';

class HashTable
{
    use HashCode;

    private $hashTable;
    private $m;
    private $size;

    public function __construct($m = 53)
    {
        $this->m = $m;
        $this->size = 0;
        for ($i = 0; $i < $m; $i++) {
            $this->hashTable[$i] = new BinarySearchTreeMap();
        }
    }

    /**
     * 将 k 转化成哈希数组里面的索引
     * @param $k
     * @return int
     */
    private function hash($k)
    {
        return $this->hashCode($k) % $this->m;
    }

    /**
     * 获取哈希表元素个数
     * @return int
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * 向哈希表中添加 key-value
     * @param $k
     * @param $v
     */
    public function add($k, $v)
    {
        $hashKey = $this->hash($k);
        //判断哈希表值对应的连表中是否包含某个值
        if ($this->hashTable[$hashKey]->contains($k)) {
            //存在，则修改原来k对应的值
            $this->hashTable[$hashKey]->set($k, $v);
        } else {
            //若不存在，则新增原来的值
            $this->hashTable[$hashKey]->add($k, $v);
            $this->size++;
        }
    }

    /**
     * 删除哈希表中 k 对应的值
     * @param $k
     */
    public function remove($k)
    {
        $hashKey = $this->hash($k);
        $reValue = null;
        if ($this->hashTable[$hashKey]->contains($k)) {
            //若包含对应的key才删除
            $reValue = $this->hashTable[$hashKey]->remove($k);
            $this->size--;
        }
        return $reValue;
    }

    /**
     *
     * 修改哈希表中key 对应的值
     */
    public function set($k, $v)
    {
        $hashKey = $this->hash($k);
        if (!$this->hashTable[$hashKey]->contains($k)) {
            throw new Exception("不存在对应的 key");
        }
        $this->hashTable[$hashKey]->set($k, $v);
    }

    /**
     * 判断哈希表中是否包含某个元素
     */
    public function contains($k)
    {
        $hashKey = $this->hash($k);
        return $this->hashTable[$hashKey]->contains($k);
    }

    /**
     * 获取哈希表中 k 对应的值
     * @param $k
     */
    public function get($k)
    {
        $hashKey = $this->hash($k);
        return $this->hashTable[$hashKey]->get($k);
    }
}